package promotion

import (
	// "fmt"
	"runtime"
	"strings"
	"time"

	"mall/common/modelx"
	"mall/common/resultx"
	"mall/service/forum/api/internal/types"

	"github.com/shopspring/decimal"
	// "github.com/sirupsen/logrus"
)

type PricingInfo struct {
	SkuId            uint64
	ProductId        uint64
	SkuPrice         decimal.Decimal
	SkuNumber        int64
	SkuAmount        decimal.Decimal //
	Freight          decimal.Decimal
	MutexType        int32
	ActivityId       uint64
	ActivityAmount   decimal.Decimal ///
	ActivityDiscount decimal.Decimal
	ActivityFixed    decimal.Decimal
	CouponAmount     decimal.Decimal ///
	FinalAmount      decimal.Decimal ///
	Status           int32
	Checked          int32
}

type OrderPricingDetailInfo struct {
	ActivityId       int64           ///
	ActivityAmount   decimal.Decimal ///
	ActivityDiscount decimal.Decimal //
	ActivityFixed    decimal.Decimal ///
	Threshold        string          ///
	Limit            decimal.Decimal ///
	Status           int             /// 0 未生效，1 已生效，-1 未达门槛
	RuleId           int64           ///
	Effect           uint32
	EffectType       uint32
	EffectValue      string
}

type OrderPricingInfo struct {
	SkusNumber       int64           //
	SkusAmount       decimal.Decimal //
	ActivityId       int64           ///
	CouponId         int64           ///
	CouponTemplateId int64           ///
	ActivityAmount   decimal.Decimal ///
	ActivityFixed    decimal.Decimal
	CouponAmount     decimal.Decimal
	CouponDiscount   decimal.Decimal
	Threshold        string          ///
	Limit            decimal.Decimal ///
	FinalAmount      decimal.Decimal ///
	Status           int             /// 0 未生效，1 已生效
	Margin           string
	Effect           uint32 /// 先记录，等待未来生效
	EffectType       uint32 ///
	EffectValue      string ///
}

// Context 上下文
type Context struct {
	ActInfo             *types.PromotionActivityInfo      ///
	UserId              uint64                            ///
	UserRank            string                            ///
	GemRatio            decimal.Decimal                   ///
	MutexMap            map[uint32]map[uint64]int64       ///
	PricingInfos        []*PricingInfo                    ///
	OrderPricingInfos   []*OrderPricingInfo               ///
	OrderPricingDetails map[int][]*OrderPricingDetailInfo ///
}

// BehaviorInterface 不同优惠活动类型的行为差异的抽象接口
type BehaviorInterface interface { ///
	// 参数校验(不同优惠活动类型实现不同)
	checkParams(ctx *Context) error
	// 获取定价信息(不同优惠活动类型实现不同)
	getPricingInfo(ctx *Context) error
	// 获取定价信息(不同优惠活动类型实现不同)
	getOrderPricingInfo(ctx *Context) error
}

// Activity 优惠活动模板
type Activity struct { ///
	// 不同优惠活动类型的抽象行为
	ConcreteBehavior BehaviorInterface
}

// checkTimeRange 校验活动是否正在进行
func (activity *Activity) CheckTimeRange(ctx *Context) (err error) { ///
	// logx.Infow("校验活动是否正在进行...")

	if len(ctx.ActInfo.TimeRange) == 2 {
		now := time.Now()
		if startedAt, err := modelx.ParseLocalTime(ctx.ActInfo.TimeRange[0]); err == nil {
			// logrus.Info(fmt.Sprintf("Activity checkTimeRange startedAt: %+v   %+v   %+v", startedAt, startedAt.After(now), now))
			if startedAt.After(now) {
				return resultx.NewErrCode(resultx.ACTIVITY_NOT_STARTED)
			}
		}
		if EndedAt, err := modelx.ParseLocalTime(ctx.ActInfo.TimeRange[1]); err == nil {
			// logrus.Info(fmt.Sprintf("Activity checkTimeRange EndedAt: %+v   %+v   %+v", EndedAt, EndedAt.Before(now), now))
			if EndedAt.Before(now) {
				return resultx.NewErrCode(resultx.ACTIVITY_ENDED)
			}
		}
	}

	return
}

func (activity *Activity) CheckMemberRestriction(ctx *Context) (err error) {
	if ctx.ActInfo.MemberRestriction != nil && len(*ctx.ActInfo.MemberRestriction) > 0 {
		if members := strings.Split(strings.ToLower(*ctx.ActInfo.MemberRestriction), ","); len(members) > 0 {
			for _, member := range members {
				if ctx.UserRank == member {
					return
				}
			}

			return resultx.NewErrCode(resultx.ACTIVITY_MEMBER_RESTRICTED)
		}
	}

	return
}

// checkParams 参数校验(不同优惠活动类型实现不同)
// 不同场景变化的算法 转化为依赖抽象
func (activity *Activity) CheckParams(ctx *Context) (err error) { ///
	// 实际依赖的接口的抽象方法
	return activity.ConcreteBehavior.checkParams(ctx)
}

// getPricingInfo 获取定价信息(不同优惠活动类型实现不同)
// 不同场景变化的算法 转化为依赖抽象
func (activity *Activity) GetPricingInfo(ctx *Context) (err error) { ///
	// 实际依赖的接口的抽象方法
	return activity.ConcreteBehavior.getPricingInfo(ctx)
}

func (activity *Activity) GetOrderPricingInfo(ctx *Context) (err error) { ///
	// 实际依赖的接口的抽象方法
	return activity.ConcreteBehavior.getOrderPricingInfo(ctx)
}

// 获取正在运行的函数名
func runFuncName() string {
	pc := make([]uintptr, 1)
	runtime.Callers(2, pc)
	f := runtime.FuncForPC(pc[0])

	return f.Name()
}
